<template>
  <section class="component data-box-page-pick">
    <div class="row between-span" v-if="showTopSlot">
      <div>
        <slot name="buttons"></slot>
      </div>
      <div>
        <slot name="append"></slot>
      </div>
    </div>
    <div class="table">
      <el-table :cell-style="cellStyle" :data="data" :emptyText="emptyText" :highlight-current-row="selectionRow!=undefined" :row-class-name="rowClassName" :row-style="rowStyle" :span-method="spanMethod" :stripe="stripe && !showCaseMark" @current-change="updateSelectionRow" @row-click="onRowClick" @select="updateSelectionList" @select-all="updateSelectionList" @sort-change="onSortChange" border ref="table" tooltip-effect="dark" :height="tableHeight()">
        <el-table-column type="selection" v-if="selectionList" width="50" reserve-selection  :selectable="checkbox"></el-table-column>
        <el-table-column :label="indexLabel" type="index" v-if="!hiddenIndex" width="60"></el-table-column>
        <slot name="columns"></slot>
      </el-table>
    </div>
    <div class="row between-span">
      <div class="databox-title">
        <slot name="footer"></slot>
      </div>
      <el-pagination :current-page.sync="page.pageIndex" :layout="page.layout" :page-size.sync="page.pageSize" :page-sizes="page.pageSizeOpts" :total="page.total" @current-change="pageIndexChange" @size-change="pageSizeChange" size="small" v-if="showPage&&page&&data&&data.length>0"></el-pagination>
    </div>
  </section>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import { Watch, Prop, Emit } from "vue-property-decorator";
import { PageService } from "~/utils/page.service";
import { SortService } from "~/utils/sort.service";
import { Table } from "element-ui";
import { namespace } from "vuex-class";
import { CaseMarkColor } from "~/config/enum.config";

@Component({
  components: {}
})
export default class DataBoxPagePick extends Vue {
  public table: any;
  private rowIndex: number = -1;
  //记录原始传入的选中列表
  private rawSelectionList:any = [];
  //记录当前页数中的初始选中列表
  private currentPageSelectList:any[] = [];
  // 数据列表

  @Prop() private data: any[];
  // 分页数据
  @Prop() private page: PageService;
  // 隐藏分页
  @Prop({ default: true })
  private showPage: any;
  // 分页数据
  @Prop() private sort: SortService;
  // 选择列表
  @Prop() private selectionList: any;
  // 选择项
  @Prop() private selectionRow: any;
  @Prop({ default: 528 })
  private maxHeight: number;
  @Prop() private height: any;

  @Prop({ type: Boolean })
  private hiddenIndex;

  //用来判断是否合并单元格
  @Prop({ type: Boolean })
  private isSpan;

  @Prop({
    type: String,
    default: "序号"
  })
  private indexLabel;
  // 列样式
  @Prop({
    type: Function,
    default: () => ""
  })
  private rowClassName;
  // 斑马线
  @Prop({
    default: true
  })
  private stripe: boolean;

  // 合并行对应的键
  @Prop({
    type: String
  })
  private rowSpanKey;

  /**
   * 是否展示caseMark
   */
  @Prop({ type: Boolean, default: false })
  private showCaseMark: boolean;

  @Prop({ type: Function })
  private cellStyle;

  /**
   *  清除选择项
   */
  public clearSelection() {
    this.table.clearSelection();
    this.table.setCurrentRow();
  }

  @Emit("onRowClick")
  private onRowClick(row, event, column) { }
  // 分页信息改变消息
  @Emit("onPageChange")
  private pageConfigChange(page) {
    return page
  }
  
  // 更新当前选择项
  @Emit("update:selectionRow")
  private updateSelectionRow(row) { }

  // 监听当前选中行变化
  @Watch("selectionRow", { immediate: true })
  private onSelectionRowChange(val: string, oldVal: string) {
    this.$nextTick(() => {
      this.table.setCurrentRow(val);
    });
  }

  private tableHeight() {
    if (this.height === "") {
      return this.maxHeight;
    } else {
      return this.height;
    }
  }

  private checkbox (row, rowIndex) {
    console.log(row)
    return row.caseSwitch === 'OPEN' ? true : false;
  }

  private get showTopSlot() {
    return this.$slots.buttons || this.$slots.append;
  }

  private get emptyText() {
    return this.data ? "暂无数据" : " ";
  }
  /**
   * 组件初始化
   */
  private mounted() {
    this.table = this.$refs["table"] as any;
    if(this.selectionList === undefined) return 
    this.rawSelectionList = this.selectionList
    this.currentPageSelectList = this.data.filter(item=>{
      return this.selectionList.some(subItem=>{
        return subItem.id === item.id
      })
    })
  }

  /**
   * 组件信息回填
   */
  private update(data) {
    this.rawSelectionList = data
    this.currentPageSelectList = this.data.filter(item=>{
      return this.selectionList.some(subItem=>{
        return subItem.id === item.id
      })
    })
  }
  
  /**
   * 监听绑定数据变化
   */
  @Watch("data")
  private onDataChanged(newVal: any, oldVal: string) {
    if(this.selectionList === undefined) return
    this.$nextTick(()=>{
      this.currentPageSelectList = newVal.filter(item=>{
        return this.selectionList.some(subItem=>{
          return subItem.id === item.id
        })
      })
      this.data.forEach(row=>{
        const checkFlag = this.selectionList.some(item=> item.id === row.id);
        this.table.toggleRowSelection(row, checkFlag);
      })
    })
  }

  // 更新选择项列表
  @Emit("update:selectionList")
  private updateSelectionList(list) {
    if(this.currentPageSelectList.length !== 0){
      this.rawSelectionList = this.rawSelectionList.filter(item=>{
        const index = this.currentPageSelectList.findIndex(subItem=>{
          return item.id === subItem.id
        })
        return index === -1 ? true : false
      })
    }
    return this.rawSelectionList.concat(list)
  }

  // 监听当前选中列表变化
  @Watch("selectionList", { immediate: true })
  private onSelectionListChanged(val: any[], oldVal: any[]) {
    if (!val) {
      return;
    }
    //  等待data 渲染完毕之后再进行选中行赋值
    this.$nextTick(() => {
      this.data.forEach(row => {
        const checkFlag = this.selectionList.includes(row);
        this.table.toggleRowSelection(row, checkFlag);
      });
    });
  }

  /**
   * 页码数量变化回调
   */
  private pageSizeChange(value) {
    this.page.pageIndex = 1;
    this.page.pageSize = value;
    this.rawSelectionList = this.selectionList
    this.pageConfigChange(this.page);
  }

  /**
   * 页码位置变化回调
   */
  private pageIndexChange(value) {
    this.page.pageIndex = value;
    this.pageConfigChange(this.page);
    this.rawSelectionList = this.selectionList
  }

  /**
   * 排序改变
   */
  private onSortChange({ column, prop, order }) {
    if (this.sort) {
      this.sort.update(prop, order);
      this.pageConfigChange(this.page);
    }
  }

  private rowStyle({ row, rowIndex }) {
    if (!this.showCaseMark) return;
    if (!row.caseMark) return;
    const color = CaseMarkColor.find(x => x.value === row.caseMark);
    if (color) {
      return {
        backgroundColor: color.color
      };
    }
  }

  private spanMethod({ row, column, rowIndex, columnIndex }) {
    if (!this.rowSpanKey) return;
    const columnProperty = this.rowSpanKey;
    if (column.property !== columnProperty) return;
    // 当前单元格的值
    const currentValue = row[columnProperty];
    const span = {
      rowspan: 0,
      colspan: 0
    };
    const beforRow = rowIndex > 0 ? this.data[rowIndex - 1] : null;
    if (beforRow && beforRow[columnProperty] === currentValue) return span;

    // 如果当前单元格的值与上一行的对应单元格的值一致，则合并行已经计算过
    span.colspan = 1;
    span.rowspan = 1;
    let nextRowIndex = rowIndex + 1;
    while (nextRowIndex < this.data.length) {
      // 如果下一行对应单元格的值与当前单元格的值一致
      const nextRowValue = this.data[nextRowIndex][columnProperty];
      if (nextRowValue === currentValue) span.rowspan += 1;
      nextRowIndex += 1;
    }
    return span;
  }

  //重置
  private reset(){
    this.rawSelectionList = []
    this.currentPageSelectList = []
  }
}
</script>

<style lang="less" scoped>
.component.data-box-page-pick {
  padding: 10px;
  & > * {
    margin-bottom: 10px;
  }
}
</style>
<style lang="less">
.data-box-page-pick.component {
  @line-height: 26px;
  .el-input-number {
    line-height: @line-height;
    width: inherit;
    &__decrease,
    &__increase {
      height: calc(@line-height - 2px);

      width: 35px;
    }
    &__increase {
      right: 5px;
    }
    &__decrease {
      left: 5px;
    }
  }
}
</style>
